/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/5/29 22:35
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.aurora.core;

import com.hyacinth.aurora.core.bean.AuroraBeanFactory;
import com.hyacinth.aurora.core.bean.BeanFactory;
import com.hyacinth.aurora.core.scanner.AuroraClassScanner;
import com.hyacinth.aurora.core.scanner.ClassScanner;
import com.hyacinth.aurora.utils.ObjectUtil;
import com.hyacinth.aurora.utils.StringUtil;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 实例工厂
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class InstanceFactory {

    /**
     * 用于缓存对应的实例
     */
    private static final Map<String, Object> cache = new ConcurrentHashMap<>();

    private static final String CLASS_SCANNER = "custom.class_scanner";

    private static final String BEAN_FACTORY = "custom.bean_factory";

    /**
     * 获取 ClassScanner
     */
    public static ClassScanner getClassScanner() {
        return getInstance(CLASS_SCANNER, AuroraClassScanner.class);
    }

    /**
     * 获取自定义bean工厂
     */
    public static BeanFactory getBeanFactory() {
        return getInstance(BEAN_FACTORY, AuroraBeanFactory.class);
    }

    @SuppressWarnings("unchecked")
    private static <T> T getInstance(String cacheKey, Class<T> defaultImplClass) {
        // 若缓存中存在对应的实例，则返回该实例
        if (cache.containsKey(cacheKey)) {
            return (T) cache.get(cacheKey);
        }
        // 从配置文件中获取相应的接口实现类配置
        String implClassName = AuroraProperties.getProperty(cacheKey);
        // 若实现类配置不存在，则使用默认实现类
        if (StringUtil.isEmpty(implClassName)) {
            implClassName = defaultImplClass.getName();
        }
        // 通过反射创建该实现类对应的实例
        T instance = ObjectUtil.newInstance(implClassName);
        // 若该实例不为空，则将其放入缓存
        if (instance != null) {
            cache.put(cacheKey, instance);
        }
        // 返回该实例
        return instance;
    }

}
